﻿using System;
using System.Collections.Generic;
using System.CodeDom;
using BMC.ARSystem;
using System.Collections;

namespace NRemedy
{
    public class GenerateSelectionProperty : IGenerateProperty
    {
        public void Create(CodeTypeDeclaration classType, string propertyName, string propertyType, Limit limit, Dictionary<string, object> attributePropertyValues, GeneratePropertyDelegate propertyDelegate, IGeneratePropertyAttribute attributeGenerator)
        {
            if (classType == null) throw new ArgumentNullException("classType");
            if (string.IsNullOrEmpty(propertyName)) throw new ArgumentNullException("propertyName");
            if (string.IsNullOrEmpty(propertyType)) throw new ArgumentNullException("propertyType");
            if (limit == null) throw new ArgumentNullException("selectionLimit");
            if (attributePropertyValues == null) throw new ArgumentNullException("attributePropertyValues");
            if (propertyDelegate == null) throw new ArgumentNullException("propertyDelegate");
            if (attributeGenerator == null) throw new ArgumentNullException("attributeGenerator");

            if (propertyDelegate(propertyName))
            {
                GenerateNameResolver gnr = new GenerateNameResolver();
                CodeMemberProperty _property = new CodeMemberProperty();
                _property.Name = propertyName;
                string _propertyType = gnr.SelectionTypeResolver(propertyName);
                _property.Type = new CodeTypeReference(_propertyType);
                _property.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                string fieldName = gnr.DefaultFieldNameResolver(propertyName);
                _property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName)));
                _property.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName), new CodePropertySetValueReferenceExpression()));
                _property.SetStatements.Add(new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), "OnPropertyChanged"), new CodeExpression[] { new CodePrimitiveExpression(propertyName) }));

                //add attribute
                attributeGenerator.Create(_property, typeof(ARFieldAttribute), attributePropertyValues);
                classType.Members.Add(_property);

                //add enum
                SelectionLimit selectionLimit = (SelectionLimit)limit;
                ArrayList values = selectionLimit.Values;
                ARSelectionType selection = ARSelectionTypeConvert.GetSelection(values);
                CodeTypeDeclaration enCode = new CodeTypeDeclaration(_propertyType);
                enCode.IsEnum = true;
                enCode.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                for (int i = 0; i < selection.item.Count; i++)
                {
                    CodeMemberField mem = new CodeMemberField(typeof(Int32), selection.item[i].value.ToString());
                    mem.Attributes = MemberAttributes.Public;
                    mem.InitExpression = new CodeSnippetExpression(selection.item[i].key.ToString());
                    enCode.Members.Add(mem);
                }

                classType.Members.Add(enCode);
            }
        }
    }
}
